home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000…tember: Reference Library / Dev.CD Sep 00 RL Disk 1.toast / mac / Technical Documentation / Develop / develop Issue 27 / develop Issue 27 code / Internet Config Assistant / toolkit / CWindows.cp < prev    next >
Encoding:
Text File  |  1996-06-30  |  16.2 KB  |  601 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        CWindows.cp
  3.  
  4.     Contains:    Layer built on top of the Window Manager
  5.  
  6.     Written by:    Arno Gourdol
  7.  
  8.     Copyright:    © 1994-1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.  
  11. */
  12.  
  13. #include "CWindows.h"
  14.  
  15. #include <LowMem.h>                 // for LMGetGrayRgn()
  16. #include <Memory.h>
  17. #include <Script.h>
  18. #include <ToolUtils.h>
  19. #include <Sound.h>
  20.  
  21. #include "CFonts.h"
  22. #include "TEnvironment.h"
  23. #include "macros.h"
  24. #include "assert.h"
  25.  
  26.  
  27.  
  28. CWindow *CWindow::gWindowList = NULL;
  29.  
  30.  
  31.  
  32. // --------------------------------------------------------------------
  33. // CWindow
  34. // --------------------------------------------------------------------
  35. // Constructor
  36.  
  37. CWindow::CWindow(UInt16 windowType) :
  38.     fWindow(NULL),
  39.     fNextWindow(NULL),
  40.     fWindowType(windowType)
  41. {
  42.     // Prepend this to the list of windows
  43.     this->SetNextWindow(gWindowList);
  44.     gWindowList = this;
  45. }
  46.  
  47.  
  48.  
  49. // --------------------------------------------------------------------
  50. // CWindow
  51. // --------------------------------------------------------------------
  52. // Destructor
  53.  
  54. CWindow::~CWindow(void)
  55. {
  56.     if (GetWindowRef() != NULL)
  57.         Close();
  58.     
  59.     // Remove this from the list of windows
  60.     if (gWindowList == this)
  61.     {
  62.         gWindowList = GetNextWindow();
  63.     }
  64.     else if (gWindowList != NULL)
  65.     {
  66.         for (CWindow *window = gWindowList; window != NULL; window = window->GetNextWindow())
  67.         {
  68.             if (window->GetNextWindow() == this)
  69.             {
  70.                 window->SetNextWindow(this->GetNextWindow());
  71.                 break;
  72.             }
  73.         }
  74.     }
  75. }
  76.  
  77.  
  78.  
  79. // --------------------------------------------------------------------
  80. // CloseRequested
  81. // --------------------------------------------------------------------
  82. // Hook function called before a window gets closed
  83. // An opportunity to ask the user to confirm the operation
  84. // Returns true if must go ahead.
  85.  
  86. Boolean CWindow::CloseRequested(void)
  87. {
  88.     return true;
  89. }
  90.  
  91.  
  92.  
  93. // --------------------------------------------------------------------
  94. // Close
  95. // --------------------------------------------------------------------
  96. // Close the window without asking the user for confirmation
  97. // Call Close after CloseRequested() has returned true
  98.  
  99. void CWindow::Close(void)
  100. {
  101.     assert(GetWindowRef() != NULL);
  102.     DisposeWindow(GetWindowRef());
  103.     fWindow = NULL;
  104. }
  105.  
  106.  
  107.  
  108. // --------------------------------------------------------------------
  109. // MenusWillShow
  110. // --------------------------------------------------------------------
  111. // Hook function called before the menus are going to be displayed
  112. // (after the user has clicked on them).
  113. // Enable/disable items appropriately
  114.  
  115. void CWindow::MenusWillShow(void)
  116. {
  117.  
  118. }
  119.  
  120.  
  121.  
  122. // --------------------------------------------------------------------
  123. // WindowActivated
  124. // --------------------------------------------------------------------
  125. // Hook function called when the window activation state changes
  126.  
  127. void CWindow::WindowActivated(Boolean active)
  128. {
  129. #pragma unused(active)
  130.  
  131. }
  132.  
  133.  
  134.  
  135. // --------------------------------------------------------------------
  136. // GetCWindow
  137. // --------------------------------------------------------------------
  138. // Return a CWindow object from a Toolbox window
  139. // Returns NULL if there is no CWindow object associated with this window
  140.  
  141. CWindow* CWindow::GetCWindow(WindowRef window)
  142. {
  143. // ??? Try to write this as a friend conversion operator
  144.     CWindow* result;
  145.     for (result = gWindowList; result != NULL; result = result->GetNextWindow())
  146.     {
  147.         if (result->GetWindowRef() == window)
  148.             break;
  149.     }
  150.     return result;
  151. }
  152.  
  153.  
  154.  
  155. // --------------------------------------------------------------------
  156. // Pulse
  157. // --------------------------------------------------------------------
  158. // Hook function called regularly
  159.  
  160. void CWindow::Pulse(void)
  161. {
  162.     // nothing to do in superclass
  163. }
  164.  
  165.  
  166.  
  167. // --------------------------------------------------------------------
  168. // ResizeBy
  169. // --------------------------------------------------------------------
  170. // Function to resize a window to the indicated relative dimensions
  171.  
  172. void CWindow::ResizeBy(GraphicalUnit dx, GraphicalUnit dy)
  173. {
  174. #pragma unused(dx, dy)
  175.     assert(false);    // Not implemented yet
  176. }
  177.  
  178.  
  179.  
  180. // --------------------------------------------------------------------
  181. // ResizeTo
  182. // --------------------------------------------------------------------
  183. // Function to resize a window to the indicated absolute dimensions
  184.  
  185. void CWindow::ResizeTo(GraphicalUnit width, GraphicalUnit height)
  186. {
  187.     SizeWindow(fWindow, width, height, true);
  188.     
  189.     SetPort(GetGrafPtr());
  190.     CRect windowRect = GetGrafPtr()->portRect;    // Use Frame() ???
  191.  
  192.     ClipRect(windowRect);
  193.     EraseRect(windowRect);
  194.     InvalRect(windowRect);                        // Update content of window later
  195. }
  196.  
  197.  
  198.  
  199. // --------------------------------------------------------------------
  200. // Zoom
  201. // --------------------------------------------------------------------
  202. // Function called to change the zoomed state of a window
  203.  
  204. void CWindow::Zoom(Boolean zoomOut)
  205. {
  206.     CRect newWindowRect;
  207.     CRect monitorRect;
  208.     
  209.     TDrawContext drawContext(GetGrafPtr());    // ZoomWindow requires the port to be set
  210.     if (drawContext.Lock())
  211.     {
  212.         {
  213.             TEnvironment environment;
  214.             environment.GetMonitorRect(Bounds(), monitorRect);    // Get the rectangle of the best monitor
  215.         }
  216.         monitorRect.SetTop(monitorRect.Top() + (LMGetMBarHeight() - 3));    // Make room for the title bar (assuming same as menu bar)
  217.         monitorRect.InsetBy(4);                // Give some edge to the window
  218.  
  219.         if (zoomOut)
  220.         {
  221.             assert(fExtent.Right() > 10);
  222.             assert(fExtent.Bottom() > 10);
  223.             
  224.             // Calculate where the new window would be if we didn't move it
  225.             newWindowRect = Bounds();
  226.             newWindowRect.SetWidth(fExtent.Right());
  227.             newWindowRect.SetHeight(fExtent.Bottom());
  228.  
  229.             if (!monitorRect.Contains(newWindowRect))
  230.             {
  231.                 newWindowRect.OffsetBy(monitorRect.Left() - newWindowRect.Left(), monitorRect.Top() - newWindowRect.Top());
  232.                 newWindowRect.SetRight(min(newWindowRect.Right(), monitorRect.Right()));
  233.                 newWindowRect.SetBottom(min(newWindowRect.Bottom(), monitorRect.Bottom()));
  234.             }
  235.  
  236.             assert(!newWindowRect.IsEmpty());
  237.             SetWindowStandardState(fWindow, newWindowRect);    // new zoom-out rect
  238.         }
  239.         else
  240.         {
  241.             // Adjust the user state to minimize moving
  242.             GetWindowUserState(fWindow, newWindowRect);
  243.  
  244.             newWindowRect.OffsetBy(Bounds().Left() - newWindowRect.Left(), Bounds().Top() - newWindowRect.Top());
  245.             newWindowRect.SetRight(min(newWindowRect.Right(), monitorRect.Right()));
  246.             newWindowRect.SetBottom(min(newWindowRect.Bottom(), monitorRect.Bottom()));
  247.             SetWindowStandardState(fWindow, newWindowRect);
  248.         }
  249.  
  250.         ClipRect(Bounds());// White out contents of window
  251.         EraseRect(Bounds());
  252.         ZoomWindow(fWindow, inZoomOut, false);        // Always zoom on the stdState
  253.  
  254.         InvalRect(Bounds());
  255.         drawContext.Unlock();
  256.     }
  257. }
  258.  
  259.  
  260.  
  261. // --------------------------------------------------------------------
  262. // MakeWindow
  263. // --------------------------------------------------------------------
  264. // Function called to construct a Toolbox window for this object
  265. // Can only be called once.
  266.  
  267. WindowRef CWindow::MakeWindow(void)
  268. {
  269.     assert(GetWindowRef() == NULL);
  270.     WindowRef aNewWindow = GetNewCWindow(128, NULL, WindowRef(-1));    // (-)
  271.     
  272.     return aNewWindow;
  273. }
  274.  
  275.  
  276.  
  277. // --------------------------------------------------------------------
  278. // Show
  279. // --------------------------------------------------------------------
  280. // Function called to show the window if it was invisible
  281. // Creates the window if it did not exist
  282.  
  283. void CWindow::Show(void)
  284. {
  285.     if (GetWindowRef() == NULL)
  286.         CreateWindow();
  287.  
  288.     ::ShowWindow(GetWindowRef());
  289. }
  290.  
  291.  
  292.  
  293. // --------------------------------------------------------------------
  294. // Hide
  295. // --------------------------------------------------------------------
  296. // Function called to hide the window
  297. // The window must have been create previouslt
  298.  
  299. void CWindow::Hide(void)
  300. {
  301.     assert(GetWindowRef() != NULL);
  302.     ::HideWindow(GetWindowRef());
  303. }
  304.  
  305.  
  306.  
  307. // --------------------------------------------------------------------
  308. // FilterEvent
  309. // --------------------------------------------------------------------
  310. // Hook functionc called before an event gets processed
  311. // Returns true if the event was handled.
  312. // It calls FilterKey
  313.  
  314. Boolean CWindow::FilterEvent(const EventRecord& event)
  315. {
  316.     Boolean result = false;    // Event not handled
  317.     
  318.     if (event.what == keyDown || event.what == autoKey)
  319.     {
  320.         UInt16 key;
  321.         UInt16 keyCode = event.message & keyCodeMask;;
  322.         UInt16 keyASCII = event.message & charCodeMask;
  323.         
  324.         if (keyASCII == 0x10)
  325.         {
  326.             // It's a function key
  327.             key = keyCode;
  328.         }
  329.         else if (keyCode == 0x01)
  330.         {
  331.             // The ESC and Clear keys return the same ASCII code
  332.             // To differentiate them, we need to look at the keycode
  333.             // as well. If it's 1, it's the ESC key.
  334.             key = keyEscape;
  335.         }
  336.         else
  337.         {
  338.             key = keyASCII;
  339.         }
  340.         result = FilterKey(event, key);
  341.     }
  342.     return result;    
  343. }
  344.  
  345.  
  346.  
  347. // --------------------------------------------------------------------
  348. // MouseDown
  349. // --------------------------------------------------------------------
  350. // Hook function called when the content of the window has been clicked
  351.  
  352. void CWindow::MouseDown(const EventRecord& event)
  353. {
  354. #pragma unused(event)
  355. }
  356.  
  357.  
  358.  
  359. // --------------------------------------------------------------------
  360. // FilterKey
  361. // --------------------------------------------------------------------
  362. // Constructor
  363.  
  364. Boolean CWindow::FilterKey(const EventRecord& event, UInt16 key)
  365. // Hook function called before key events are processed
  366. // Returns true if the event was handled.
  367. {
  368. #pragma unused(event)
  369. #pragma unused(key)
  370.     return false;    // Event not handled
  371. }
  372.  
  373.  
  374.  
  375. // --------------------------------------------------------------------
  376. // MoveTo
  377. // --------------------------------------------------------------------
  378. // Function to change the location of the window
  379.  
  380. void CWindow::MoveTo(const CPoint& location)
  381. {
  382.     assert(GetWindowRef() != NULL);
  383.     
  384.     MoveWindow(GetWindowRef(), location.X(), location.Y(), false);
  385.     
  386.     FrameMoved(location);
  387. }
  388.  
  389.  
  390.  
  391. // --------------------------------------------------------------------
  392. // FrameResized
  393. // --------------------------------------------------------------------
  394. // Hook function called when the window has been resized
  395.  
  396. void CWindow::FrameResized(GraphicalUnit newWidth, GraphicalUnit newHeight)
  397. {
  398. #pragma unused(newWidth, newHeight)
  399. }
  400.  
  401.  
  402.  
  403. // --------------------------------------------------------------------
  404. // FrameMoved
  405. // --------------------------------------------------------------------
  406. // Hook function called when the window location has changed
  407.  
  408. void CWindow::FrameMoved(const CPoint& newLocation)
  409. {
  410. #pragma unused(newLocation)
  411.  
  412. }
  413.  
  414.  
  415.  
  416. // --------------------------------------------------------------------
  417. // ForceOnScreen
  418. // --------------------------------------------------------------------
  419. // Function that ensures that the window is visible on screen
  420.  
  421. void CWindow::ForceOnScreen(void)
  422. {
  423. #if 1
  424.     enum { kMinDragArea = 4 };
  425.  
  426.     CTempRgn theDragRgn;
  427.     WindowRecord & theWindowRecord = *((WindowPeek)GetWindowRef());
  428.     DiffRgn(theWindowRecord.strucRgn, theWindowRecord.contRgn, theDragRgn);// strucRgn less contRgn ≈≈ drag rgn
  429.     if (EmptyRgn(theDragRgn))
  430.         CopyRgn(theWindowRecord.strucRgn, theDragRgn);// at least get the strucRgn 
  431.  
  432.     CPoint contentRegionInset = CPoint((*theWindowRecord.contRgn)->rgnBBox.left, (*theWindowRecord.contRgn)->rgnBBox.top)
  433.                                 - CPoint((*theWindowRecord.strucRgn)->rgnBBox.left, (*theWindowRecord.strucRgn)->rgnBBox.top);
  434.  
  435.     // get the desktop rgn, inset by a minimal drag area 
  436.     CTempRgn theSectRgn(LMGetGrayRgn());
  437.     InsetRgn(theSectRgn, kMinDragArea, kMinDragArea);    // inset theSectRgn 
  438.     SectRgn(theDragRgn, theSectRgn, theSectRgn);        // do drag rgn && desktop rgn instersect ? 
  439.  
  440.     if (EmptyRgn(theSectRgn))
  441.     {
  442.         GraphicalUnit deltaX;
  443.         GraphicalUnit deltaY;
  444.         CRect visScreenRect;
  445.         CRect theFrame(GetWindowRef()->portRect);
  446.  
  447.         // since we don't _really_ know what the drag rgn is, we'll assume that moving the
  448.         // topleft pt of the window on screen is sufficient to make it draggable, so calculate
  449.         // the deltas necessary to move the topleft pt into visible screen CRect.
  450.     
  451.         this->GetMaxIntersectedDevice(visScreenRect);
  452.         visScreenRect.InsetBy(kMinDragArea);
  453.     
  454.         if (theFrame.Top() < visScreenRect.Top())
  455.             deltaY = (visScreenRect.Top() - theFrame.Top() + contentRegionInset.Y());
  456.         else if (theFrame.Top() > visScreenRect.Bottom())
  457.             deltaY = (visScreenRect.Bottom() - theFrame.Top() - contentRegionInset.Y());
  458.     
  459.         if (theFrame.Left() < visScreenRect.Left())
  460.             deltaX = (visScreenRect.Left() - theFrame.Left() + contentRegionInset.X());
  461.         else if (theFrame.Left() > visScreenRect.Right())
  462.             deltaX = (visScreenRect.Right() - theFrame.Right() - contentRegionInset.X());
  463.  
  464.         this->MoveTo(CPoint(theFrame.Left() + deltaX, theFrame.Top() + deltaY));
  465.     }
  466. #else
  467.     // This routine has been promoted into the API, but not documented.
  468.     // I hope this is a correct interpretation of what it does!
  469.     CheckWindowPosition(GetDialogWindow(fDlog), ccDragBar, false);
  470. #endif
  471. }
  472.  
  473.  
  474.  
  475. // --------------------------------------------------------------------
  476. // GetMaxIntersectedDevice
  477. // --------------------------------------------------------------------
  478. // Returns the device that intersects most of the specified rectangle
  479.  
  480. GDHandle CWindow::GetMaxIntersectedDevice(CRect& screenRect)
  481. {
  482.     long maxSectArea = 0;
  483.     CTempRgn structure;
  484.     GetWindowStructureRgn(GetWindowRef(), structure);
  485.     Rect globalStrucRect = (*structure)->rgnBBox;
  486.  
  487.     GDHandle aGDHandle = GetDeviceList();
  488.     GDHandle maxSectGD = GetMainDevice();            // set as best choice default 
  489.     while (aGDHandle)
  490.     {                                        // calc which scrn intersects largest part of window
  491.         if (TestDeviceAttribute(aGDHandle, screenDevice) && TestDeviceAttribute(aGDHandle, screenActive))
  492.         {
  493.             Rect aGDScreenRect = (*aGDHandle)->gdRect;
  494.             CRect gdSectRect;
  495.  
  496.             if (SectRect(&globalStrucRect, &aGDScreenRect, gdSectRect))
  497.             {
  498.                 long sectArea = gdSectRect.Width() * gdSectRect.Height();
  499.                 if (sectArea > maxSectArea)        // do we have a new winner? 
  500.                 {
  501.                     maxSectArea = sectArea;
  502.                     maxSectGD = aGDHandle;
  503.                 }
  504.             }
  505.         }
  506.         aGDHandle = GetNextDevice(aGDHandle);
  507.     }
  508.  
  509.     if (maxSectGD != GetMainDevice())
  510.         screenRect = (*maxSectGD)->gdRect;
  511.     else
  512.     {                                        // Account for menu bar on the main screen.
  513.                                             // Don't just assume that it's at the top of
  514.                                             // the screen!
  515.         CTempRgn tempRgn;
  516.         Rect gdRect = (*maxSectGD)->gdRect;
  517.  
  518.         RectRgn(tempRgn, &gdRect);                        // main screen with menubar 
  519.         SectRgn(tempRgn, LMGetGrayRgn(), tempRgn);        // GetGrayRgn == desktop rgn w/o menubar 
  520.         screenRect = (*(RgnHandle) tempRgn)->rgnBBox;    // => main screen w/o menubar 
  521.     }
  522.     return maxSectGD;
  523. }
  524.  
  525.  
  526.  
  527. // --------------------------------------------------------------------
  528. // DrawDispatch
  529. // --------------------------------------------------------------------
  530. // Callback function that dispatch to the draw method
  531.  
  532. pascal void CWindow::DrawDispatch(short depth, short deviceFlags,
  533.                          GDHandle targetDevice, CWindow* window)
  534. {
  535. #pragma unused(targetDevice)
  536.     // Clip to the visible region
  537.     SetClip(window->GetGrafPtr()->visRgn);
  538.     
  539.     Boolean isColor = ((deviceFlags & (1L << gdDevType)) == 0);
  540.     TDrawContext drawContext(window->GetGrafPtr(), depth, isColor);
  541.     if (drawContext.Lock())
  542.     {
  543.         window->Draw(drawContext);
  544.         drawContext.Unlock();
  545.     }
  546. }
  547.  
  548.  
  549.  
  550. // --------------------------------------------------------------------
  551. // DoUpdate
  552. // --------------------------------------------------------------------
  553. // Function that processes all the update events, calling the Draw()
  554. // method as appropriate
  555.  
  556. void CWindow::DoUpdate(RgnHandle area)
  557. {
  558.     // Set a "normal" graphic env. 
  559.     SetPort(GetGrafPtr());
  560.     PenNormal();
  561.     //ForeColor(blackColor);
  562.     //BackColor(whiteColor);
  563.  
  564.     // Loop thru all the devices and call the DrawDispatch proc each time
  565.     {
  566.         DeviceLoopDrawingUPP upp = NewDeviceLoopDrawingProc(DrawDispatch);
  567.         
  568.         DeviceLoop(area, upp, (long)this, (DeviceLoopFlags)0);
  569.             
  570.         DisposeRoutineDescriptor(upp);
  571.     }
  572.  
  573.     ClipRect(&GetGrafPtr()->portRect);    // ??? Use Frame() instead
  574. }
  575.  
  576.  
  577.  
  578. // --------------------------------------------------------------------
  579. // DrawGrowIcon
  580. // --------------------------------------------------------------------
  581. // Function that draws the grow icon
  582.  
  583. void CWindow::DrawGrowIcon(TDrawContext& drawContext) const
  584. {
  585.     //    Draw the grow icon, clipped to only the grow icon
  586.     // (draws annoying outline for scrollbars else)
  587.     CRect growIconRect(drawContext.Bounds());
  588.     
  589.     growIconRect.SetLeftTop(CPoint(growIconRect.Right() - 15, growIconRect.Bottom() - 15));
  590.  
  591.     {
  592.         CRect area((**GetGrafPtr()->visRgn).rgnBBox);
  593.         if (::SectRect(growIconRect, area, growIconRect))
  594.         {
  595.             ::ClipRect(growIconRect);
  596.             ::DrawGrowIcon(GetWindowRef());
  597.             ::SetClip(GetWindowPort(fWindow)->visRgn);                // Restore the clip region to the window content
  598.         }
  599.     }
  600. }
  601.